import type { SearchSelectorConfig } from '../../../../module/page_enhancer/appearance/style_enhancement/platforms'
import type { SoPageTypeResult } from './types'
import {
  SO_ENCYCLOPEDIA_HOSTNAME,
  SO_NEWS_HOSTNAME,
  SO_VIDEO_HOSTNAME,
  SO_WEN_KU_HOSTNAME,
} from '../../../../types/constants'
import { PageRoute } from '../../../abstract/page_route'
import { SO_SEARCH_PAGE_SELECTORS, SoPageType } from './types'

export class SoPage extends PageRoute {
  readonly name: string = 'SoPage'
  private static instance: SoPage
  get pageType(): SoPageType | 'default' {
    return this.getCurrentPageMeta().type
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): SoPage {
    if (!SoPage.instance) {
      SoPage.instance = new SoPage()
    }
    return SoPage.instance
  }

  /**
   * 获取结果选择器
   */
  getResultSelectors(pageType?: SoPageType, includeHideElement: boolean = true): SearchSelectorConfig {
    return this.resultSelectors(
      {
        pageType: pageType || this.pageType,
        selectorConfig: SO_SEARCH_PAGE_SELECTORS,
        includeHideElement,
        supportedPages: [
          SoPageType.Web,
        ],
      },
    )
  }

  /**
   * 获取当前页面类型
   */
  public getCurrentPageMeta(): SoPageTypeResult {
    const url = this.getCurrentUrl()
    const hostname = new URL(url).hostname
    const path = new URL(url).pathname

    // 404 页面检测
    const notFoundResult = this.detectNotFoundPage()
    if (notFoundResult)
      return notFoundResult

    // 首页
    if (/^\/?$/.test(path)) {
      if (hostname === SO_VIDEO_HOSTNAME) {
        return { type: SoPageType.IndexVideo }
      }
      else if (hostname === SO_ENCYCLOPEDIA_HOSTNAME) {
        return { type: SoPageType.IndexEncyclopedia }
      }
      else if (hostname === SO_WEN_KU_HOSTNAME) {
        return { type: SoPageType.IndexWenku }
      }
      else {
        return { type: SoPageType.IndexSearch }
      }
    }

    // 基础页面检测
    const pageResult = this.detectPages(hostname, path)
    if (pageResult)
      return pageResult

    // 未定义页面
    return { type: SoPageType.Undefined }
  }

  /**
   * 检测 404 页面
   */
  private detectNotFoundPage(): SoPageTypeResult | null {
    const pageNotFoundRules = [
      /404.*Not Found/i, // 不区分大小写
    ]

    if (pageNotFoundRules.some(regex => regex.test(document.title))) {
      return { type: SoPageType.NotFound }
    }
    else if ($('#main .advice span#url_404').length > 0) {
      return { type: SoPageType.NotFound }
    }
    else if (/360文库 - 404/.test(document.title)) {
      return { type: SoPageType.WenkuNotFound }
    }

    return null
  }

  /**
   * 检测其他功能页面
   */
  private detectPages(hostname: string, basePath: string): SoPageTypeResult | null {
    const pageDetectors: Array<[RegExp, (...args: any[]) => SoPageTypeResult]> = [
      [/^\/s\/?$/, () => {
        if (hostname === SO_VIDEO_HOSTNAME) {
          return { type: SoPageType.Video }
        }
        else if (hostname === SO_WEN_KU_HOSTNAME) {
          return { type: SoPageType.Wenku }
        }
        else {
          return { type: SoPageType.Web }
        }
      }],
      [/^\/ns\/?$/, () => {
        if (hostname === SO_NEWS_HOSTNAME) {
          return { type: SoPageType.News }
        }
        else {
          return { type: SoPageType.Undefined }
        }
      }],
      [/^\/search\/?$/, () => {
        if (hostname === SO_ENCYCLOPEDIA_HOSTNAME) {
          return { type: SoPageType.Encyclopedia }
        }
        else {
          return { type: SoPageType.Undefined }
        }
      }],
    ]

    for (const [regex, handler] of pageDetectors) {
      const match = basePath.match(regex)
      if (match) {
        return handler(match)
      }
    }

    return null
  }
}
